package com.example.ssm.context;

import com.example.ssm.enums.PaymentType;
import com.example.ssm.strategy.PaymentStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 支付上下文类
 * 负责根据支付信息自动选择合适的支付策略
 */
@Component
public class PaymentContext {
    
    // 支付宝账号模式（邮箱或手机号）
    private static final Pattern ALIPAY_PATTERN = Pattern.compile("^(1[3-9]\\d{9}|[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})$");
    
    // 微信支付标识模式
    private static final Pattern WECHAT_PATTERN = Pattern.compile("^wx_[a-zA-Z0-9]{16,}$");
    
    // 银行卡号模式（简化版，实际应更复杂）
    private static final Pattern BANK_CARD_PATTERN = Pattern.compile("^\\d{16,19}$");
    
    // 策略映射表
    private final Map<String, PaymentStrategy> strategyMap = new HashMap<>();
    
    /**
     * 构造方法，通过Spring自动注入所有策略实例
     * @param applicationContext Spring应用上下文
     */
    @Autowired
    public PaymentContext(ApplicationContext applicationContext) {
        // 初始化策略映射表
        for (PaymentType type : PaymentType.values()) {
            PaymentStrategy strategy = applicationContext.getBean(type.getStrategyBeanName(), PaymentStrategy.class);
            strategyMap.put(type.getCode(), strategy);
        }
    }
    
    /**
     * 根据支付账号自动选择并执行合适的支付策略
     * @param paymentAccount 支付账号（可以是支付宝账号、微信支付标识或银行卡号）
     * @param amount 支付金额
     * @param orderId 订单ID
     * @return 支付结果
     */
    public String processPayment(String paymentAccount, BigDecimal amount, String orderId) {
        // 根据账号特征自动识别支付方式
        PaymentType paymentType = identifyPaymentType(paymentAccount);
        
        if (paymentType == null) {
            return "无法识别的支付账号格式: " + paymentAccount;
        }
        
        // 获取对应的支付策略
        PaymentStrategy strategy = strategyMap.get(paymentType.getCode());
        
        if (strategy == null) {
            return "未找到对应的支付策略: " + paymentType.getDesc();
        }
        
        // 验证支付参数
        if (!strategy.validate(amount, orderId)) {
            return "支付参数验证失败";
        }
        
        // 执行支付
        return strategy.pay(amount, orderId);
    }
    
    /**
     * 根据支付方式代码获取对应的支付策略
     * @param paymentTypeCode 支付方式代码
     * @return 支付策略
     */
    public PaymentStrategy getStrategy(String paymentTypeCode) {
        return strategyMap.get(paymentTypeCode);
    }
    
    /**
     * 根据支付账号特征识别支付方式
     * @param paymentAccount 支付账号
     * @return 支付方式枚举
     */
    private PaymentType identifyPaymentType(String paymentAccount) {
        if (paymentAccount == null || paymentAccount.trim().isEmpty()) {
            return null;
        }
        
        if (ALIPAY_PATTERN.matcher(paymentAccount).matches()) {
            return PaymentType.ALIPAY;
        } else if (WECHAT_PATTERN.matcher(paymentAccount).matches()) {
            return PaymentType.WECHAT;
        } else if (BANK_CARD_PATTERN.matcher(paymentAccount).matches()) {
            return PaymentType.BANK_CARD;
        }
        
        return null;
    }
    
    /**
     * 根据支付参数自动选择并执行合适的支付策略
     * @param paymentParams 支付参数
     * @return 支付结果
     */
    public String processPayment(Map<String, Object> paymentParams) {
        // 提取必要的支付参数
        String paymentAccount = (String) paymentParams.get("account");
        BigDecimal amount = new BigDecimal(paymentParams.get("amount").toString());
        String orderId = (String) paymentParams.get("orderId");
        
        // 调用账号识别方法处理支付
        return processPayment(paymentAccount, amount, orderId);
    }
    
    /**
     * 根据支付方式代码处理支付
     * @param paymentTypeCode 支付方式代码
     * @param amount 支付金额
     * @param orderId 订单ID
     * @return 支付结果
     */
    public String processPaymentByCode(String paymentTypeCode, BigDecimal amount, String orderId) {
        PaymentStrategy strategy = strategyMap.get(paymentTypeCode);
        
        if (strategy == null) {
            return "不支持的支付方式: " + paymentTypeCode;
        }
        
        // 验证支付参数
        if (!strategy.validate(amount, orderId)) {
            return "支付参数验证失败";
        }
        
        // 执行支付
        return strategy.pay(amount, orderId);
    }
}
